﻿// luaScriptModule.cpp : 定义 DLL 应用程序的导出函数。
//

#include "stdafx.h"
#include <event/SEventSlot.h>
#include <string/strcpcvt.h>
#include "ScriptModule-qjs.h"
using namespace qjsbind;

namespace SOUI
{
    BOOL ExportSoui(qjsbind::Context* context);

    static void qjsLog(const char* szLog) {
        SLOGI2("qjs_log") << szLog;
    }

    SScriptModule_Qjs::SScriptModule_Qjs(qjsbind::Runtime* pRuntime)
    {
        m_context = new qjsbind::Context(pRuntime);
        m_context->SetLogFunc(qjsLog);

        ExportSoui(m_context);
    }


    SScriptModule_Qjs::~SScriptModule_Qjs()
    {
        delete m_context;
    }


    LPCSTR SScriptModule_Qjs::getIdentifierString() const
    {
        return "SOUI.Script.Qjs";
    }

    void SScriptModule_Qjs::executeScriptFile( LPCSTR pszScriptFile )
    {
        SStringW str = S_CA2W(pszScriptFile, CP_UTF8);
        FILE* f = _wfopen(str.c_str(), L"r");
        if (!f) return;
        fseek(f, 0, SEEK_END);
        long len = ftell(f);
        fseek(f, 0, SEEK_SET);
        char* buf = (char*)malloc(len+1);
        if (!buf) {
            fclose(f);
            return;
        }
        int nReaded=fread(buf, 1, len, f);
        buf[nReaded] = 0;
        fclose(f);
        Value val = m_context->Eval(buf, nReaded, "<eval>", JS_EVAL_TYPE_MODULE);
        if (val.IsException()) {
            m_context->DumpError();
        }
    }


    void SScriptModule_Qjs::executeScriptBuffer( const char* buff, size_t sz )
    {
        m_context->Eval(buff, sz, "<eval>");
    }

    BOOL SScriptModule_Qjs::executeScriptedEventHandler( LPCSTR handler_name, IEvtArgs *pArg)
    {
        qjsbind::Value global = m_context->Global();
        if (!global.HasProperty(handler_name))
        {
            SLOGE2("qjs_log") << "global this has no object named as "<<handler_name;
            return FALSE;
        }
        qjsbind::Value fun = global.GetProperty(handler_name);
        if (!fun.IsFunction()) {
            SLOGE2("qjs_log") << handler_name <<" is not function in global this";
            return FALSE;
        }
        qjsbind::Value arg = NewValue(*m_context, pArg);
        qjsbind::Value ret = m_context->Call(global, fun, 1, &arg);
        if (ret.IsException()) {
            m_context->DumpError();
            return FALSE;
        }
        return TRUE;
    }

	int SScriptModule_Qjs::executeMain(THIS_ HINSTANCE hInst,LPCSTR pszWorkDir, LPCSTR pszArgs)
	{
        qjsbind::Value args[3];
        args[0] = NewValue(*m_context, hInst);
        args[1] = NewValue(*m_context, pszWorkDir);
        args[2] = NewValue(*m_context, pszArgs);
        qjsbind::Value ret = m_context->Invoke(m_context->Global(), "main", 3, args);
        if (ret.IsException())
        {
            m_context->DumpError();
            return -1;
        }
		return ret.ToInt32();
	}


    SScriptFactory::SScriptFactory() {
        m_runtime = new qjsbind::Runtime();
    }

    SScriptFactory::~SScriptFactory() {
        delete m_runtime;
    }

    HRESULT SScriptFactory::CreateScriptModule( IScriptModule ** ppScriptModule )
    {
        *ppScriptModule= new SOUI::SScriptModule_Qjs(m_runtime);
        return S_OK;
    }

	namespace SCRIPT_QJS
	{
		BOOL SCreateInstance(IObjRef ** ppScript)
		{
			*ppScript= new SOUI::SScriptFactory;
			return TRUE;
		}
	}

}

EXTERN_C BOOL Script_Qjs_SCreateInstance(IObjRef ** ppScript)
{
	return SOUI::SCRIPT_QJS::SCreateInstance(ppScript);
}

//////////////////////////////////////////////////////////////////////////
